const obj = {
  ff: 'name',
  gg: 1,
  obj: {
    name: '123',
  },
  arr: [1,2,3]
}
function deepClone(obj) {
  const targetObj = obj.constructor === Array ? [] : {};
  for (const keys in obj) {
    if (obj.hasOwnProperty(keys)) {
      if (obj[keys] && typeof obj[keys] === 'object') {
        targetObj[keys] = deepClone(obj[keys]);
      } else {
        targetObj[keys] = obj[keys];
      }
    }
  }
  return targetObj;
}

function deepCloneCatch(target, map=new Map()) {
  if(typeof target === 'object' && target !== null) {
    let cache = map.get(target)
    if(cache) {
      return cache
    }
    let isArray = Array.isArray(target)
    const result = isArray ? [] : {}
    map.set(target, result)
    if (isArray) {
      target.forEach((item, index) => {
        result[index] = deepCloneCatch(item, map)
      })
    } else {
      Object.keys(target).forEach(key => {
        result[key] = deepCloneCatch(target[key], map)
      })
    }
    return result
  } else {
    return target
  }
}
const a = deepCloneCatch(obj);
obj.ff = 'name111';
console.log(obj); // { ff: 'name111', gg: 1, obj: { name: '123' }, arr: [ 1, 2, 3 ] }
console.log(a); // { ff: 'name', gg: 1, obj: { name: '123' }, arr: [ 1, 2, 3 ] }
